#include "widgets.h"
#include <algorithm>
#include <cmath>
#include <sstream>
#include "utils.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

void example_window(){

		bool my_tool_active = true;
		// Create a window called "My First Tool", with a menu bar.
		ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar);
		if (ImGui::BeginMenuBar())
		{
			if (ImGui::BeginMenu("File"))
			{
				if (ImGui::MenuItem("Open..", "Ctrl+O")) { /* Do stuff */ }
				if (ImGui::MenuItem("Save", "Ctrl+S"))   { /* Do stuff */ }
				if (ImGui::MenuItem("Close", "Ctrl+W"))  { my_tool_active = false; }
				ImGui::EndMenu();
			}
			ImGui::EndMenuBar();
		}

		float my_color[4];
		
		// Edit a color stored as 4 floats
		ImGui::ColorEdit4("Color", my_color);

		// Generate samples and plot them
		float samples[100];
		for (int n = 0; n < 100; n++)
			samples[n] = sinf(n * 0.2f + ImGui::GetTime() * 1.5f);
		ImGui::PlotLines("Samples", samples, 100);

		// Display contents in a scrolling region
		ImGui::TextColored(ImVec4(1,1,0,1), "Important Stuff");
		ImGui::BeginChild("Scrolling");
		for (int n = 0; n < 50; n++)
			ImGui::Text("%04d: Some text", n);
		ImGui::EndChild();
		ImGui::End();

}

//---------------------------------------ListWindows------------------------------------

ListWindows& ListWindows::getInstance()
{
	static ListWindows instance;

	return instance;
}

std::list<Window*> ListWindows::windows;

ListWindows::ListWindows(){}
ListWindows::~ListWindows(){}

void ListWindows::setWindow(Window* w)
{
	windows.push_back(w);
}

std::list<Window*> ListWindows::getWindows()
{
	return windows;
}

void ListWindows::erase(Window * w)
{
	auto it = std::find(windows.begin(), windows.end(), w);
	windows.erase(it);
}

//------------------------------------------Window-------------------------------------

Window::Window(Window* w)
{
	ListWindows::getInstance().setWindow(w);
	mPointer = this;

}

Window::~Window()
{
	ListWindows::getInstance().erase(mPointer);
}

void Window::Show(){}

//----------------------------------Console-------------------------------------
Console::Console():Window(this)
{

}

Console::~Console()
{

}

void Console::ExecuteCommands(std::string cmd)
{
	std::vector<std::string> cmds;
	std::stringstream ss(cmd);
	std::string s;
	while (ss>>s) {
		cmds.push_back(s);
	}

	for (int i=0; i<sizeof(CMap)/sizeof(Cmd_Map); i++) {
		//不区分大小写比较
		if (StringCaseCmp(CMap[i].name, cmds[0])){
			//参数校验
			if (checkParams(cmds, CMap[i])) {
				return;
			}
			InputTextItems.clear();
			CMap[i].func(std::vector<std::string>(cmds.begin()+1, cmds.end()), InputTextItems);
			return;
		}
	}
	//不存在的命令
	InputTextItems.push_back("'"+cmds[0]+"': Invalid Command!!!");
}

bool Console::checkParams(const std::vector<std::string>& cmds, const Cmd_Map& standar)
{
	std::string name = cmds[0];
	//检查参数个数
	int param_size = cmds.size() - 1;
	if (standar.psize != 0 && param_size != standar.psize) {
		InputTextItems.push_back("参数个数错误!!!\n");
		InputTextItems.push_back(standar.doc);
		return 1;
	}
	//检查参数类型:有点难设计
	// for(int i = 1;  i<cmds.size(); i++) {
	// 	char type = standar.params[i-1].type;
	// 	switch (type) {
	// 		case 'i':
	// 			cmds[i]
	// 	}
	// }
	return 0;
}

inline int callback(ImGuiInputTextCallbackData* data)
{
	//处理inputtext的一些默认行为，如tab补全，上下回溯历史等

	return 0;
}

void Console::Show()
{

	bool bClientActive = true;
	ImGuiWindowFlags_ flag = ImGuiWindowFlags_MenuBar;
	ImGui::Begin("Client", &bClientActive,flag);

	if (ImGui::BeginMenuBar()) {
		ImGui::EndMenuBar();
	}
	ImGui::TextWrapped("Welcome Video Factory!!!");
	ImGui::SeparatorText("terminal");
	
	if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -20), true, ImGuiWindowFlags_HorizontalScrollbar)) {

		for (auto item : InputTextItems) {
			ImGui::TextUnformatted(item.c_str());
		}
	
	}
	ImGui::EndChild();

	ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | 
											ImGuiInputTextFlags_EscapeClearsAll |
											ImGuiInputTextFlags_CallbackCompletion |
											ImGuiInputTextFlags_CallbackHistory;
	char buf[256] = {0,};
	bool reclaim_focus = false;
	if (ImGui::InputText("input", buf, IM_ARRAYSIZE(buf), input_text_flags, callback, NULL)) {
		std::string s(buf);
		s.erase(0, s.find_first_not_of("\t "));
		s.erase(s.find_last_not_of("\t ")+1);
		printf("%s\n", s.c_str());
		if (s.length()) {
			ExecuteCommands(s);
		}
		reclaim_focus = true;
	}

	ImGui::SetItemDefaultFocus();
	if (reclaim_focus) {
		ImGui::SetKeyboardFocusHere(-1);
	}

	ImGui::End();
}

MediaPlayer::MediaPlayer():Window(this)
{
	mSourceName = "Media Player";
	mTextureId = 0;
	mWidth = mHeight = 0;
	bool ret = LoadTextureFromFile("MyImage01.jpg", mTextureId, &mWidth, &mHeight);
	IM_ASSERT(ret);
}

MediaPlayer::~MediaPlayer()
{

}

void MediaPlayer::Start(std::string name)
{
	mSourceName = name;
}

void MediaPlayer::Show()
{
	ImGui::Begin(mSourceName.c_str());
		ImGui::Text("pointer = %p", mTextureId);
		ImGui::Text("size = %d x %d", mWidth, mHeight);
		ImGui::Image((ImTextureID)(intptr_t)mTextureId, ImVec2(mWidth, mHeight));
	ImGui::End();
}

bool MediaPlayer::LoadTextureFromFile(std::string path, SDL_Texture*&texture, int* w, int* h)
{
	int width = 0;
	int height = 0;
	//加载图片数据
	unsigned char* pixels;
	pixels = stbi_load(path.c_str(), &width, &height, NULL, 4);
	if (pixels == NULL) {
		ALOGE("Load Image %s Failed\n", path.c_str());
		return false;
	}

	texture = SDL_CreateTexture(MainWindow::renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height);
	if (texture == nullptr) {
		ALOGE("Create Texture Failed!!!");
		return false;
	}

	// SDL_Rect rect = {0, 0, 100, 100};
	//
	SDL_UpdateTexture(texture, NULL, pixels, 4 * width);
    // SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
    // SDL_SetTextureScaleMode(texture, SDL_ScaleModeLinear);
	stbi_image_free(pixels);
	*w = width;
	*h = height;
}

//--------------------------------------MainWindow-------------------------------------

SDL_Window* MainWindow::window;
SDL_Renderer* MainWindow::renderer;

MainWindow::MainWindow():mIo()
{
    // Setup SDL
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
    {
        printf("Error: %s\n", SDL_GetError());
		exit(-1);
    }

    // From 2.0.18: Enable native IME.
#ifdef SDL_HINT_IME_SHOW_UI
    SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
#endif

    // Create window with SDL_Renderer graphics context
    SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE);
	window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", 
										SDL_WINDOWPOS_CENTERED, 
										SDL_WINDOWPOS_CENTERED, 
										1280, 720, window_flags);
    renderer = SDL_CreateRenderer(window, -1,
												SDL_RENDERER_PRESENTVSYNC |
												SDL_RENDERER_ACCELERATED);
    if (renderer == NULL)
    {
        SDL_Log("Error creating SDL_Renderer!");
		exit(-2);
    }
    //SDL_RendererInfo info;
    //SDL_GetRendererInfo(renderer, &info);
    //SDL_Log("Current SDL_Renderer: %s", info.name);

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
	mIo = &io;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

	//加载cjk字体
	io.Fonts->AddFontFromFileTTF("fonts/NotoSansCJKsc-Bold.otf", 20, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());

    // Setup Dear ImGui style
    ImGui::StyleColorsDark();
    //ImGui::StyleColorsLight();

    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
    ImGui_ImplSDLRenderer_Init(renderer);

    bg_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
}

MainWindow::~MainWindow()
{

    // Cleanup
    ImGui_ImplSDLRenderer_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();


}

int MainWindow::run()
{
	//main loop
	bool done = false;
	while(!done) {

        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            ImGui_ImplSDL2_ProcessEvent(&event);
            if (event.type == SDL_QUIT)
                done = true;
            if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
                done = true;
        }

        // Start the Dear ImGui frame
        ImGui_ImplSDLRenderer_NewFrame();
        ImGui_ImplSDL2_NewFrame();
        ImGui::NewFrame();

		bool show_demo_window = true;
		{
			ImGui::ShowDemoWindow(&show_demo_window);
			//example_window();
			std::list<Window*> windows = ListWindows::getInstance().getWindows();
			for (auto win : windows) {
				auto pw = dynamic_cast<Window*>(win);
				pw->Show();
			}
		}
        // Rendering
        ImGui::Render();
        SDL_RenderSetScale(renderer, mIo->DisplayFramebufferScale.x, mIo->DisplayFramebufferScale.y);
        SDL_SetRenderDrawColor(renderer, (Uint8)(bg_color.x * 255), (Uint8)(bg_color.y * 255), (Uint8)(bg_color.z * 255), (Uint8)(bg_color.w * 255));
        SDL_RenderClear(renderer);
        ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
        SDL_RenderPresent(renderer);
	}

	return 0;
}
